#include "engine.h"

#ifndef __gameconstants
#include "gameconstants.h"
#define __gameconstants
#endif

Engine::Engine(void) {
	this->window = new CL_DisplayWindow("Chili Con Carnage 15k",
			RESOLUTION_WIDTH, RESOLUTION_HEIGHT, false, false);
	//this->console = new CL_ConsoleWindow("ChiliConCarnage15k Console");
	this->graphicEngine = new Graphics(window);
	this->soundEngine = new Sound();
	this->controls = new Control(window);
	this->model = GameModel::getInstance();
	this->resourceManager = ResourceManager::getInstance();

	loadImages();
	loadLevel();
}

Engine::~Engine(void) {
	delete (window);
	//delete (console);
	delete (graphicEngine);
	delete (soundEngine);
	delete (controls);
	ResourceManager::destroyInstance();
}

void Engine::start() {
	mainloop();
}

void Engine::end() {
	model->isGameRunning = false;
}

void Engine::mainloop() {
	Player* player = resourceManager->getPlayer();
	//run sound
	soundEngine->start();
	// mainloop in der alles ablaeuft
	while (model->isGameRunning) {

		// hier kann man der grafikengine sagen wo man welche objekte zeichnen will
#ifdef WIN32
		UNISLEEP((int)(1000.0/RENDER_FPS));
#endif
		// usereingabe abfragen

		switch (model->getGameState()) {
		case GameState::INGAME:
			//player->setPlayerState(PlayerDirection::NONE);
			controls->getInput();
			// freien fall bzw. sprung fortsetzen
			if (model->fallDownActive) {
				model->fallDown();
			} else {
				if (model->continueJump)
					model->continueJump = model->executePlayerJump();
			}

			if (player->getScore() > 0) {
				player->setScore(player->getScore() + SCORE_TIME_DECREASE);

			}
			if (player->getHasHabanero()) {
				if (player->getHabaneroTimer() > 0) {
					player->setHabaneroTimer(player->getHabaneroTimer() - 1);

				} else {
					player->setHasHabanero(false);
				}
			}
			if (player->getIsDead()) {
				if (player->getDeathTimer() > 0) {
					player->setDeathTimer(player->getDeathTimer() - 1);

				} else {
					player->setIsDead(false);
				}
			}

			// grafiken zeichnen
			graphicEngine->draw();
			break;
		case GameState::GAME_OVER:
			controls->getInputForEnding();
			graphicEngine->drawGameOverScreen();
			break;
		case GameState::FINISHED:
			controls->getInputForEnding();
			graphicEngine->drawEndingScreen();
			break;
		default:
			controls->getInputForEnding();
			break;
		}

		CL_KeepAlive::process(0);
	}

}

void Engine::loadLevel() {
	LevelLoader loader("res/level1.txt");
	resourceManager->setLevel(loader.getLevelData());

	//Spielerposition an den Startpunkt setzen
	resourceManager->getPlayer()->setPosX(
			static_cast<float> (resourceManager->getLevel()->getStartX()));
	resourceManager->getPlayer()->setPosY(
			static_cast<float> (resourceManager->getLevel()->getStartY()));
}

void Engine::loadImages() {

	// items laden
	try {
		CL_Sprite* beerImage = new CL_Sprite(window->get_gc(), "res/beer.png");
		CL_Sprite* coinImage = new CL_Sprite(window->get_gc(), "res/coin.png");
		CL_Sprite* habaneroImage = new CL_Sprite(window->get_gc(),
				"res/habanero.png");
		CL_Sprite* kebapImage =
				new CL_Sprite(window->get_gc(), "res/kebap.png");
		CL_Sprite* toiletbrushImage = new CL_Sprite(window->get_gc(),
				"res/toiletbrush.png");

		Item* beer = new Item(beerImage);
		Item* coin = new Item(coinImage);
		Item* habanero = new Item(habaneroImage);
		Item* kebap = new Item(kebapImage);
		Item* toiletbrush = new Item(toiletbrushImage);

		resourceManager->addGameItem(ITEM_BEER, beer);
		resourceManager->addGameItem(ITEM_COIN, coin);
		resourceManager->addGameItem(ITEM_HABANERO, habanero);
		resourceManager->addGameItem(ITEM_KEBAP, kebap);
		resourceManager->addGameItem(ITEM_TOILET_BRUSH, toiletbrush);
	} catch (CL_Exception e) {
		CL_Console::write(e.message);
	}

	// weltobjekte laden

	try {
		CL_Sprite* crateImage =
				new CL_Sprite(window->get_gc(), "res/crate.png");
		CL_Sprite* grassImage =
				new CL_Sprite(window->get_gc(), "res/grass.png");
		CL_Sprite* wallImage = new CL_Sprite(window->get_gc(), "res/wall.png");
		CL_Sprite* finishImage =
				new CL_Sprite(window->get_gc(), "res/goal.png");
		CL_Sprite* cloudBackground = new CL_Sprite(window->get_gc(),
				"res/clouds.jpg");

		Object* crate = new Object(crateImage);
		Object* grass = new Object(grassImage);
		Object* wall = new Object(wallImage);
		Object* finish = new Object(finishImage);
		Object* clouds = new Object(cloudBackground);

		resourceManager->addGameObject(OBJECT_CRATE, crate);
		resourceManager->addGameObject(OBJECT_GRASS, grass);
		resourceManager->addGameObject(OBJECT_WALL, wall);
		// ziel
		resourceManager->addGameObject(PLAYER_TARGET, finish);
		resourceManager->addGameObject(BACKGROUND_CLOUDS, clouds);
	} catch (CL_Exception e) {
		CL_Console::write(e.message);
	}

	try {
		// stehendes bild
		CL_Sprite* playerImage = new CL_Sprite(window->get_gc(),
				"res/walk3.png");

		// gehanimation
		std::vector<CL_Sprite*>* playerAnimation =
				new std::vector<CL_Sprite*>();
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk1.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk2.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk3.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk4.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk5.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk6.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk6.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk7.png"));
		playerAnimation->push_back(new CL_Sprite(window->get_gc(),
				"res/walk8.png"));

		// stehendes bild r�ckw�rts
		CL_Sprite* playerImage_mirrored = new CL_Sprite(window->get_gc(),
				"res/walk3_mirrored.png");

		// gehanimation r�ckw�rts
		std::vector<CL_Sprite*>* playerAnimation_mirrored = new std::vector<
				CL_Sprite*>();
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk1_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk2_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk3_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk4_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk5_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk6_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk6_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk7_mirrored.png"));
		playerAnimation_mirrored->push_back(new CL_Sprite(window->get_gc(),
				"res/walk8_mirrored.png"));

		resourceManager->setPlayer(new Player(playerImage, playerAnimation));
		resourceManager->getPlayer()->setPlayerGraphics_mirrored(
				playerImage_mirrored, playerAnimation_mirrored);

	} catch (CL_Exception e) {
		CL_Console::write(e.message);
	}

	// gegner laden
	try {
		CL_Sprite* enemyImage =
				new CL_Sprite(window->get_gc(), "res/enemy.png");
		Enemy* enemy = new Enemy(enemyImage);
		resourceManager->setEnemy(enemy);
	} catch (CL_Exception e) {
		CL_Console::write(e.message);
	}
}

